package com.xinruke.hostels.manage.user.service;

import com.xinruke.hostels.common.cache.ManageUserCache;
import com.xinruke.hostels.common.constants.LoginConstants;
import com.xinruke.hostels.common.constants.RedisConstants;
import com.xinruke.hostels.common.constants.SysDicConstant;
import com.xinruke.hostels.common.mybatis.MyExample;
import com.xinruke.hostels.common.po.XtYewuyonghu;
import com.xinruke.hostels.common.po.YewuyonghuCaozuoRizhi;
import com.xinruke.hostels.common.service.OperateLogService;
import com.xinruke.hostels.common.util.CustomSecurity;
import com.xinruke.hostels.common.util.JwtUtil;
import com.xinruke.hostels.common.vo.ResultVO;
import com.xinruke.hostels.common.cache.vo.LoginManageResultVO;
import com.xinruke.hostels.common.vo.query.EConditionOperator;
import com.xinruke.hostels.common.vo.query.QueryConditions;
import com.xinruke.hostels.manage.user.interfaces.dto.login.LoginDTO;
import com.xinruke.hostels.manage.user.interfaces.dto.login.LoginManageValidateDTO;
import com.xinruke.hostels.manage.user.interfaces.dto.login.LoginManageValidateResultDTO;
import com.xinruke.hostels.manage.user.interfaces.dto.login.LoginResultDTO;
import com.xinruke.hostels.manage.user.mapper.XtYewuyonghuMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName LoginService
 * @CreateDate 2019/6/15
 * @Author FengXinQiang
 * @Version V1.0.0.0
 * @Decription 登录Service
 */
@Service
@Slf4j
public class LoginService {
    @Autowired
    XtYewuyonghuMapper yewuyonghuMapper;

    @Resource(name = "commonRedisTemplate")
    RedisTemplate commonRedisTemplate;

    @Value("${login.max-valid-second}")
    private long loginMaxValidSecond;

    @Autowired
    OperateLogService operateLogService;
    @Autowired
    ManageUserCache manageUserCache;

    /**
     * 登录
     *
     * @param loginDTO
     * @return
     */
    public ResultVO<LoginResultDTO> userLogin(LoginDTO loginDTO) {
        ResultVO<LoginResultDTO> resultVO = ResultVO.fail();
        LoginResultDTO loginResultDTO = new LoginResultDTO();

        //根据登录账号，获取用户信息
        String loginCode = loginDTO.getLoginCode();
        QueryConditions queryConditions = new QueryConditions();
        queryConditions.addCondition("yonghuming", EConditionOperator.EQULS, loginCode);
        queryConditions.addCondition("shanchubiaoshi", EConditionOperator.EQULS, SysDicConstant.DELFLAG_0);
        MyExample myExample = new MyExample(XtYewuyonghu.class, queryConditions);

        List<XtYewuyonghu> yewuyonghuList = yewuyonghuMapper.selectByExample(myExample);
        if (CollectionUtils.isEmpty(yewuyonghuList) || yewuyonghuList.size() != 1) {
            resultVO.setMessage("用户不存在或密码错误");
            return resultVO;
        }

        //验证用户登录信息，对密码做加密处理后验证是否正确
        XtYewuyonghu yewuyonghu = yewuyonghuList.get(0);

        String password = loginDTO.getLoginPassword();
        password = CustomSecurity.createUserPassword(yewuyonghu.getYonghuming(), yewuyonghu.getYan(), password);
        if (!password.equals(yewuyonghu.getMima())) {
            resultVO.setMessage("用户不存在或密码错误");
            return resultVO;
        }

        String token = JwtUtil.createManageToken(loginCode, null);

        BeanUtils.copyProperties(yewuyonghu, loginResultDTO);
        loginResultDTO.setToken(token);
        loginResultDTO.setYonghuId(yewuyonghu.getId());

        if (loginMaxValidSecond <= 0) {
            loginMaxValidSecond = 60 * 20;
        }

        LoginManageResultVO loginResultVO = new LoginManageResultVO();
        BeanUtils.copyProperties(yewuyonghu, loginResultVO);
        loginResultVO.setToken(token);

        YewuyonghuCaozuoRizhi yewuyonghuCaozuoRizhi = new YewuyonghuCaozuoRizhi(YewuyonghuCaozuoRizhi.YEWUYONGHUCAOZUORIZHI_CAOZUO_DENGLU, "登录", resultVO.getMessage());
        yewuyonghuCaozuoRizhi.setYewuyonghuId(yewuyonghu.getId());
        yewuyonghuCaozuoRizhi.setYewuyonghumingcheng(yewuyonghu.getYonghuming());
        operateLogService.writeOperateLog(yewuyonghuCaozuoRizhi);

        //将登录信息放入缓存
        commonRedisTemplate.opsForValue().set(RedisConstants.MANAGE_LOGIN_TOKEN_KEY_PREFIX + loginCode, loginResultVO, loginMaxValidSecond, TimeUnit.SECONDS);
        log.info("将登录信息放入缓存，" + RedisConstants.MANAGE_LOGIN_TOKEN_KEY_PREFIX + loginCode + loginMaxValidSecond + TimeUnit.SECONDS);

        resultVO.setCode(ResultVO.SUCCESS);
        resultVO.setMessage("登录成功");
        resultVO.setData(loginResultDTO);

        return resultVO;
    }

    /**
     * 登录验证
     *
     * @param loginValidateDTO
     * @return
     */
    public ResultVO<LoginManageValidateResultDTO> loginValidate(LoginManageValidateDTO loginValidateDTO) {
        ResultVO<LoginManageValidateResultDTO> resultVO = ResultVO.fail();
        LoginManageValidateResultDTO loginValidateResultDTO = new LoginManageValidateResultDTO();

        String token = loginValidateDTO.getToken();
        String loginCode = JwtUtil.getLoginCode(token);

        //从缓存中获取登录信息并验证
        LoginManageResultVO loginResultVO = (LoginManageResultVO) commonRedisTemplate.opsForValue().get(RedisConstants.MANAGE_LOGIN_TOKEN_KEY_PREFIX + loginCode);
        if (loginResultVO != null) {
            String loginToken = loginResultVO.getToken();
            if (token.equals(loginToken)) {
                if (loginMaxValidSecond <= 0) {
                    loginMaxValidSecond = 60 * 20;
                }
                //重新设置token的过期时间
                commonRedisTemplate.expire(RedisConstants.MANAGE_LOGIN_TOKEN_KEY_PREFIX + loginCode, loginMaxValidSecond, TimeUnit.SECONDS);

                BeanUtils.copyProperties(loginResultVO, loginValidateResultDTO);
                loginValidateResultDTO.setYonghuId(loginResultVO.getId());

                resultVO.setCode(ResultVO.SUCCESS);
                resultVO.setMessage("登录验证通过");
                resultVO.setData(loginValidateResultDTO);
            }
        }

        return resultVO;
    }

    /**
     * 退出当前登录用户
     *
     * @return
     */
    public ResultVO userLoginOut() {
        ResultVO resultVO = ResultVO.fail();

        String loginCode = "";
        int yewuyonghuId = -1;
        String yewuyonghumingcheng = "";
        try {
            LoginManageResultVO loginManageResultVO = manageUserCache.getLoginManageUserInfo();
            loginCode = loginManageResultVO.getYonghuming();
            yewuyonghuId = loginManageResultVO.getId();
            yewuyonghumingcheng = loginManageResultVO.getYonghuming();
        } catch (Exception e) {
        }

        if (StringUtils.isEmpty(loginCode)) {
            try {
                HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
                String token = request.getHeader(LoginConstants.HEADER_TOKEN_NAME);
                loginCode = JwtUtil.getLoginCode(token);
            } catch (Exception e) {
            }
        }

        YewuyonghuCaozuoRizhi yewuyonghuCaozuoRizhi = new YewuyonghuCaozuoRizhi(YewuyonghuCaozuoRizhi.YEWUYONGHUCAOZUORIZHI_CAOZUO_DENGLU, "退出", resultVO.getMessage());
        yewuyonghuCaozuoRizhi.setYewuyonghuId(yewuyonghuId);
        yewuyonghuCaozuoRizhi.setYewuyonghumingcheng(yewuyonghumingcheng);
        operateLogService.writeOperateLog(yewuyonghuCaozuoRizhi);

        commonRedisTemplate.delete(RedisConstants.MANAGE_LOGIN_TOKEN_KEY_PREFIX + loginCode);

        resultVO = ResultVO.success();

        return resultVO;
    }

}
